﻿/**
 * @fileOverview 浏览器判别工具
 * 
 * @version qinglan_Browser 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 浏览器信息
 * 
 * @namespace
 * @type Object
 */
qinglan.Browser = qinglan.Browser || {};
/**
 * 是否为IE浏览器
 * 
 * @public
 * @field
 * @return {Boolean} 是否为IE浏览器
 */
qinglan.Browser.isIE = !!document.all;
﻿/**
 * @fileOverview 类扩展
 * 
 * @version qinglan_extend 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};

/**
 * 扩展类命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Extend = qinglan.Extend || {};
/**
 * 简单的进行函数扩展
 * 
 * @param {Object}
 *            target 目标对象,需要扩展的对象
 * @param {Object}
 *            prototypes 扩展对象
 * @param {Boolean}
 *            isStatic 是否使用静态方式进行扩展
 * @return {Object} 扩展好的target
 * @function
 * @static
 * @public
 */
qinglan.Extend.simple = function(target, prototypes, isStatic) {
	for (var i in prototypes) {
		(isStatic == true || isStatic == 1) ? target[i] = prototypes[i] : (!target.prototype && (target.prototype ={}) && (target.prototype[i] = prototypes[i]));
	}
	return target;
};
﻿// @include "Array.js"
// @include "Argument.js"
// @include "../extend/Debug.js"
/**
 * @fileOverview 命名空间实现工具
 * 
 * @version qinglan_Object 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 命名空间实现类
 * 
 * @type Object
 */
qinglan.Namespace = qinglan.Namespace || {};
/**
 * 进行命名空间分割
 * 
 * @param {String}
 *            nameSpace 命名空间以'.'分割
 * @return {Object} ns：命名空间分割数组, len : 命名空间分割长度
 */
qinglan.Namespace._parseNamespace = function(nameSpace) {
	var nsArray = nameSpace.split('.');
	return {
		ns : nsArray,
		len : nsArray.length
	};
};
/**
 * 创建命名空间,如果没有指定上下文,默认是window
 * 
 * @param {String}
 *            nameSpace 命名空间以'.'分割
 * @param {Object}
 *            context 上下文
 * @param {Boolean}
 *            ismanual 是否手动完成最后对象初始化
 */
qinglan.Namespace.create = function(nameSpace, context, ismanual) {
	context = context || window;
	var nsObj = qinglan.Namespace._parseNamespace(nameSpace);
	var nsLast = qinglan.Array.getTheLast(nsObj.ns);
	for (var i = 0; i < nsObj.len - 1; i++) {
		context[nsObj.ns[i]] = context[nsObj.ns[i]] || {};
		context = context[nsObj.ns[i]] || {};
	}
	if (!ismanual) {
		!context[nsLast] && (context[nsLast] = {});
		context = context[nsLast];
	}
	return {
		instance : context,
		key : nsLast
	};
};
/**
 * 得到命名空间所指向的对象<br/> 当然,这里有更快的实现方式,用eval(nameSpace)即可,但是eval是高危函数,所以采取了这种方法
 * 
 * @param {String}
 *            nameSpace 命名空间以'.'分割
 * @param {Object}
 *            context 上下文,默认是window
 * @return {Object} 命名空间指向的对象
 */
qinglan.Namespace.get = function(nameSpace, context) {
	context = context || window;
	var nsObj = qinglan.Namespace._parseNamespace(nameSpace);
	for (var i = 0; i < nsObj.len; i++) {
		context[nsObj.ns[i]] = context[nsObj.ns[i]] || null;
		if (context[nsObj.ns[i]] == null) {
			qinglan.Debug.error('The nameSpace : [' + nameSpace
					+ '] is not definded!!');
			return null;
		};
		context = context[nsObj.ns[i]] || {};
	}
	return context;
};
/**
 * 创建命名空间数组<br/> 根据传进来的arguments创建命名空间字串
 * 
 * @param {String}
 *            arguments 方法参数
 * 
 * @return {String} 命名空间字串
 */
qinglan.Namespace.generate = function() {
	var nsArray = [];
	qinglan.Array.each(qinglan.Argument.toArray(arguments), function(value) {
				nsArray.push(value);
			});
	return nsArray.join('.');
};
﻿// @include "Namespace.js"
// @include "Typs.js"
// @include "Extend.js"
// @include "Function.js"
// @include "Argument.js"
// @include "Object.js"
/**
 * @fileOverview 模块引入工具
 * 
 * @version qinglan_Module 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 模块引入工具命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Module = qinglan.Module || {};

/**
 * 存放模块信息
 * 
 * @type Object
 */
qinglan.Module.cache = {
	ReqModules : {},
	DefaultDelayTime : 10,
	LoadingScripts : {},
	LoadingModules : {},
	LoadedScripts : {},
	LoadedModules : {}
};
/**
 * 创建模块
 * @param {String} name 模块名字
 * @param {String}{Array} urls 模块自身js
 * @param {Object} opt 设置参数
 * @return {qinglan.Module.createModule} 模块
 */
qinglan.Module.createModule = function(name,urls,opt){
	this.name = name;
	/**
	 * 本模块引用js
	 * @field
	 */
	this.urls = [];
	/**
	 * 依赖模块
	 * @field
	 */
	this.requirements = [];
	/**
	 * 加载参数设置
	 * @field
	 */
	this.opt = qinglan.Extend.simple({isAsyn:true,delay:qinglan.Module.cache.DefaultDelayTime},opt,1);

	/**
	 * 注册依赖模块
	 * @param {String}{Array} 依赖模块
	 * @function
	 */
	this.require = function(moduleLIst){
		var args = qinglan.Argument.toArray(arguments);
		qinglan.Object.each(args,function(param){
			qinglan.Type.isArray(param) ? qinglan.Object.each(param,function(p){
				this.requirements.push({'name' : p});
			},this) : this.requirements.push({'name' : param});
		},this);
	};

	qinglan.Type.isArray(urls) ? this.urls = urls : 	this.urls.push(urls);
	
	return this;
};

/**
 * 注册模块
 * @param {String} name 模块名字
 * @param {String}{Array} urls 模块自身js
 * @param {Object} opt 设置参数
 * @param {Boolean} rewrite 进行模块重写
 * @return {qinglan.Module.createModule} 模块对象
 */
qinglan.Module.register = function(name,urls,opt,rewrite){
	var ReqModules = qinglan.Module.cache.ReqModules;
	var module = new qinglan.Module.createModule(name,urls,opt);
	if(ReqModules[module.name]){
		rewrite ? (ReqModules[module.name] = module && qinglan.Debug.info('Module : ['+module.name+'] will be Overwritten!')) : qinglan.Debug.info('Module : ['+module.name+']  was already registered!');
	}else{
		ReqModules[module.name] = module;
		qinglan.Debug.info('Module : ['+module.name+']  was registered!');
	}
	return module;
};
/**
 * 加载模块
 * 
 * @param {qinglan.Module.createModule} module 模块对象
 * @param {Function} callback 回调函数
 */
qinglan.Module.loadModule = function(module,callback){
	var Module = qinglan.Module;
	var loadScript = Module.cache.LoadedScripts;
	var loadingScript = Module.cache.LoadingScripts;
	var totalLoadLen = module.urls.length;
	var finishCount = 0;
	
	var checkScriptLoad = function(){
		var falg = true;
		qinglan.Object.each(module.urls,function(url){
			if(!loadScript[url]){falg = false;}
		});
		return falg;
	};

	var defaultCallback = function(url,flag){
		qinglan.Debug.info('Script : ['+url+'] was loaded ' + (flag ? 'success' : 'failed'))+'!';
		loadScript[url] = flag;
		delete loadingScript[url];
		finishCount++;
		if(finishCount == totalLoadLen && callback) {
			 callback(module.name,checkScriptLoad());
		}
		return false;
	};
 
	qinglan.Object.each(module.urls,function(url){
		if(!loadScript[url] && !loadingScript[url]){
			loadingScript[url] = true;
			module.opt.isAsyn ? Module._asynLoadScript(module.name,url,module.opt.delay,defaultCallback) :  Module._xhrLoadScrip(module.name,url,defaultCallback) ;
		}else{
			qinglan.Debug.info('Script : ['+url+'] was already ' + (loadingScript[url] ? 'loading' : 'loaded'))+'!';
		}
	});
};
/**
 * 使用xhr加载js
 * @param {String} moduleName 模块名字
 * @param {String} url 加载js的路径 
 * @param {Function} callback 回调队列
 */
qinglan.Module._xhrLoadScript = function(moduleName,url,callback){
	var xhr;
    if (window.XMLHttpRequest)
		xhr = new XMLHttpRequest();
	else if (window.ActiveXObject) {
		xhr = new ActiveXObject("Microsoft.XMLHTTP"); 
	}
	xhr.onreadystatechange = function(){
		if(xhr.readyState == 4){
			if( xhr.status == 200){
				qinglan.Module._injectScript(xhr.responseText,moduleName);
				qinglan.Module.cache.LoadedScripts[url] = true;
				callback && callback(url,true);
			}else if(xhr.status >= 400){
				callback && callback(url,false);
			}
		}
	};
    xhr.open("GET", url, true);
    xhr.send(null);
};
/**
 * 使用scriptTag加载js
 * @param {String} moduleName 模块名字
 * @param {String} url 加载js的路径
 * @param {Number} delay 延迟的时间
 * @param {Function} callback 回调队列
 */
qinglan.Module._asynLoadScript = function(moduleName,url,delay,callback){
	var scriptNode = qinglan.Module._createScriptNode(moduleName);
	scriptNode.onload= scriptNode.onreadystatechange = function(){
		if ((!scriptNode.readyState) || scriptNode.readyState == "loaded" || scriptNode.readyState == "complete" || scriptNode.readyState == 4 && scriptNode.status == 200) {
			callback && callback(url,true);	     	
	    }
	    return false;
	};
	scriptNode.onerror = function(){
		callback && callback(url,false);
		return false;
	};
	scriptNode.setAttribute('src',url);
	document.getElementsByTagName("head")[0].appendChild(scriptNode);
};

/**
 * 创建script标签
 * @param {String} scriptName 节点名字
 * @return {Element} script节点
 */
qinglan.Module._createScriptNode = function(scriptName) {
    var scriptNode = document.createElement("script");
    scriptNode.setAttribute("type", "text/javascript");
    scriptNode.setAttribute("language", "Javascript");
    try {
        scriptNode.setAttribute("name", scriptName);
    } catch (err) { }
    return scriptNode;    
};
/**
 * 将请求得到js插入到dom中
 * @param {String} scriptText 
 * @param {String} scriptName
 */
qinglan.Module._injectScript = function (scriptText, scriptName) {
    var scriptNode = qinglan.Module._createScriptNode(scriptName);
    scriptNode.text = scriptText;
    document.getElementsByTagName("head")[0].appendChild(scriptNode);
};
/**
 * 模块主函数
 * @param {String}{Array} moduleName 要使用的模块的名字
 * @param {Function} callback 加载模块之后的回调函数
 * @param {Object} context 回调绑定对象
 * @return {}
 * 
 * @function
 * @private
 * 
 */
qinglan.Module.use= function(moduleName, callback, context){
	var Module = qinglan.Module;
	var module = Module.cache.ReqModules[moduleName];
	var loadModule = Module.cache.LoadedModules;
	var loadingModule = Module.cache.LoadingModules;
	var totalLen = module.requirements.length;
	var finishCount = 0;
	
	if(!module){
		qinglan.Debug.error('Module : ['+moduleName+'] was not registered!!');
		callback && callback(moduleName,false);
		return false;
	}
	if(loadModule[moduleName] || loadingModule[moduleName]){//如果已经加载了就不用再加载咯
		qinglan.Debug.info('Module : ['+moduleName+'] was already'+(loadingModule[moduleName] ? ' loading ' : ' loaded ')+ ' !!');
		callback && callback(moduleName,true);
		return true;		
	}
	
	var checkModuel = function(){
		var flag = true;
		qinglan.Object.each(module.requirements,function(reqModule){
			if(!Module.cache.LoadedModules[reqModule.name]){flag = false;}	
		});
		return flag;
	};
	
	var doLoadModule = function (cb,context){
		loadingModule[moduleName] = true;
		Module.loadModule(module,function(name,flag){
				qinglan.Debug.info('Module : ['+name+'] was loaded ' + (flag ? 'success' : 'failed'))+'!';
				loadModule[moduleName] = flag;
				delete loadingModule[moduleName];
				cb && cb.call(context,checkModuel());
			});
	};
	
	var defaultCallback = function(reqModuleName,flag){
		finishCount++;
		if(finishCount == totalLen){
			doLoadModule(callback,context);
		}
		return false;
	};
	
	totalLen == 0 ? doLoadModule(callback,context) : qinglan.Object.each(module.requirements,function(reqModule){
		qinglan.Module.use(reqModule.name,defaultCallback,context);
	});
	
};

﻿/**
 * @fileOverview 基础工具类
 * 
 * @version qinglan_util 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 基础工具类
 * 
 * @namespace
 * @type Object
 */
qinglan.Util = qinglan.Util || {};
﻿// @include "../code/Type.js"
/**
 * @fileOverview 模版类
 * 
 * @version qinglan_tmpl 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 模版命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Tmpl = qinglan.Tmpl || {};
/**
 * 进行简单的字符串模版替换<br/> 主要使用正则进行参数的匹配和替换<br/> 模版中需要替换的数据名称和obj中的一致并且用'{'和'}'括起来<br/>
 * 另外,如果模版中有的数据obj中没有则默认为空('')
 * 
 * @param {String}
 *            str 需要替换的模版
 * @param {Object}
 *            obj 模版数据来源
 * @return {String} 生成后的具体数据
 */
qinglan.Tmpl.smTmpl = function(str, obj) {
	if (!qinglan.Type.isString(str)) {
		return '';
	}
	if (!(qinglan.Type.isObject(obj) && 'isPrototypeOf' in obj)) {
		return str;
	}
	return str.replace(/\{([^{}]+)\}/g, function(match, key) {
				var value = obj[key];
				return (value !== undefined) ? '' + value : '';
			});
};
﻿/**
 * @fileOverview 字符串工具类
 * 
 * @version qinglan_string 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 基础工具类
 * 
 * @namespace
 * @type Object
 */
qinglan.String = qinglan.String || {};
/**
 * 去除字符串两边的空白
 * 
 * @param {String}
 *            str 字符串
 * @return {String} 去除两变空白的字串
 */
qinglan.String.trim = function(str) {
	return str.replace(/(^\s*)|(\s*$)/g, '');
};
﻿/**
 * @fileOverview 参数扩展工具
 * 
 * @version qinglan_argument 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 参数扩展命名空间
 * 
 * @type Object
 */
qinglan.Argument = qinglan.Argument || {};
/**
 * 把方法参数转换为数组
 * 
 * @param {Object}
 *            args 方法参数
 * @param {Number}
 *            num 截取参数索引
 * @return {Object}{Array} arguments的数组形式
 */
qinglan.Argument.toArray = function(args, num) {
	return Array.prototype.slice.call(args, num || 0);
};
﻿// @include "Browser.js"
// @include "Type.js"
// @include "Array.js"
// @include "../extend/Debug.js"
/**
 * @fileOverview 基础对象类
 * 
 * @version qinglan_Object 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 基础工具类
 * 
 * @namespace
 * @type Object
 */
qinglan.Object = qinglan.Object || {};
/**
 * 将对象转换为json字串
 * 
 * @param {Object}
 *            obj 对象
 * @return {String} 转换后的字符串
 */
qinglan.Object.toJsonString = function(obj) {
	if (qinglan.Type.isString(obj)) {
		qinglan.Debug.info('The typeof obj : [' + obj + '] is String');
		return obj.toString();
	}
	if (qinglan.Type.isUndefined(obj)) {
		return 'undefined';
	}
	if (qinglan.Type.isNull(obj)) {
		return 'null';
	}
	if (qinglan.Type.isObject(obj)) {
		var result = [];
		if (qinglan.Type.isArray(obj)) {
			for (var i = 0; i < obj.length; i++)
				result.push(qinglan.Object.toJsonString(obj[i]));
			result = "[" + result.join() + "]";
		} else {
			for (var i in obj)
				result.push("\"" + i + "\":"
						+ qinglan.Object.toJsonString(obj[i]));
			result = "{" + result.join() + "}";
		}
		return result;
	} else {
		return obj.toString();
	}
};
/**
 * Each 方法
 * 
 * @param {Object} obj 需要被遍历的对象
 * @param {Function} fun 遍历的时候执行的方法
 * @param {Object} context 执行上下文
 * 
 * @function
 * @public
 */
qinglan.Object.each = function(obj,fun,context){
	if(qinglan.Type.isArray(obj)){
		qinglan.Array.each(obj,fun,context);
	}else{
		for (var index in obj){
			fun.call(context,obj[index],index,obj);
		}
	}
};
﻿// @include "Namespace.js"
// @include "Typs.js"
// @include "Extend.js"
// @include "Function.js"
// @include "Argument.js"
/**
 * @fileOverview 类声明
 * 
 * @version qinglan_Class 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 类工具命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Class = qinglan.Class || {};
/**
 * 创建一个类<br/> 可以独立使用
 * 
 * @param {Object}
 *            baseClass 基类
 * @param {Object}
 *            extend 扩展类
 * @param {Boolean}
 *            staticMethod 是否使用静态方法扩展
 * @return {Object} 扩展后的类
 * @function
 * @static
 * @public
 */
qinglan.Class.create = function(baseClass, extend, staticMethod) {
	var klass = baseClass ? baseClass.extend({}, true) : function() {
	};
	var ext = extend || {};
	if (baseClass) {
		klass = baseClass.extend({}, true);
	} else {
		klass = function() {
		};
		klass.extend = function(ext, createNewClass) {
			var target = this;
			if (createNewClass) {
				target = arguments.callee.call(function() {
						}, this.prototype);
				target.extend = this.extend;
				target.create = this.create;
			}
			for (var i in ext) {
				target.prototype[i] = ext[i];
			}
			return target;
		};
		klass.create = ext.init || function() {
			return new this();
		};
	}
	if (staticMethod) {
		for (var i in ext) {
			klass[i] = ext[i];
		}
	} else {
		klass.extend(ext);
	}
	return klass;
};
/**
 * 创建模块应用
 * 
 * @param {String}
 *            nameSpace 命名空间
 * @param {Object}{Function}
 *            prototype 对象的类成员属性
 * @param {Object}
 *            staticMod 对象的静态类方法
 * @param {Object}
 *            context 上下文 所生命的命名空间将会挂在这个上下文里面,默认是window
 * @return {Object} 模块的类
 * @function
 * @static
 * @public
 */
qinglan.Class.mode = function(nameSpace, prototypes, staticMod, context) {
	/**
	 * 得到prototype的对象
	 */
	function firePrototype(proto) {
		return qinglan.Type.isFunction(proto) ? proto.call() : proto;
	}

	// 扩展默认的constructor和init函数
	prototypes = firePrototype(prototypes);
	prototypes = qinglan.Extend.simple({
				constructor : qinglan.Function.emptyFun,
				init : qinglan.Function.emptyFun
			}, prototypes, 1);

	var ns = qinglan.Namespace.create(nameSpace, context,true);
	!ns.instance[ns.key] && (ns.instance[ns.key] = {});
	!ns.instance[ns.key]._constructor
			&& (ns.instance[ns.key]._constructor = prototypes.constructor);
	!ns.instance[ns.key]._init && (ns.instance[ns.key]._init = prototypes.init);
	delete prototypes.constructor;
	delete prototypes.init;
	ns.instance[ns.key] = (function(self) {
		var that = self;
		function _init() {
			that._constructor.apply(this, arguments);
			that._init.apply(this, arguments);
		}
		return function() {
			_init.apply(this, arguments);
		};
	})(ns.instance[ns.key]);
	qinglan.Extend.simple(ns.instance[ns.key], prototypes, false);
	qinglan.Extend.simple(ns.instance[ns.key], firePrototype(staticMod), true);
	return ns.instance[ns.key];
};
// @include "../code/Browser.js"
// @include "../code/Type.js"
// @include "../extend/Debug.js"
/**
 * @fileOverview 页面节点操作工具
 * 
 * @version qinglan_dom 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 页面节点操作节点命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Math = qinglan.Math || {};
/**
 * 根据随机数范围产生随机数
 * 
 * @param {Number}
 *            start 随机数下限
 * @param {Number}
 *            end 随机数上限
 * @param {Boolean}
 *            isInt 是否为整数
 * @return {Number} 产生的随机数
 */
qinglan.Math.random = function(start, end, isInt) {
	if (isInt) {
		return Math.floor(Math.random(end - start) + start);
	} else {
		return (Math.random(end - start) + start);
	}
};
﻿// @include "Type.js"
/**
 * @fileOverview 基础扩展类
 * 
 * @version qinglan_Array 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 数组工具命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Array = qinglan.Array || {};
/**
 * 遍历数组的方法
 * 
 * @param {Array}
 *            array 数组
 * @param {Function}
 *            fun 对每个元素执行的方法,将会把当前处理到的元素作为参数传给这个function
 * @param {Object}
 *            context 方法的上下文
 */
qinglan.Array.each = function(array, fun, context) {
	if (qinglan.Type.isFunction(array.forEach)) {
		array.forEach(fun, context);
	} else {
		if (qinglan.Type.isArray(array)) {
			for (var i = 0, len = array.length; i < len; i++) {
				fun.call(context, array[i], i, array);
			}
		}
	}
};
/**
 * 判断数组是否有某个元素
 * 
 * @param {Array}
 *            array 数组
 * @param {Object}
 *            item 需要检查的对象
 */
qinglan.Array.has = function(array, item) {
	for (var i = 0, len = array.length; i < len; i++) {
		if (array[i] == item)
			return true;
	}
	return false;
};
/**
 * 从数组里面移除某个元素,如果有重复的话,会全部移除
 * 
 * @param {Array}
 *            array 数组
 * @param {Object}
 *            item 需要移除的对象
 */
qinglan.Array.remove = function(array, item) {
	var j = array.length;
	for (var i = 0; i < j; i++) {
		if (array[i] == item) {
			array.splice(i, 1);
			j--;
		}
	}
};
/**
 * 获取数组最大值或最小值
 * 
 * @param {Array}
 *            array 数组 PS:需要是能转换为比较大小的数组
 * @param {String}
 *            type 获取值的方式,最大为max,最小为min
 */
qinglan.Array.getExtreme = function(array, type) {
	var result = 0;
	for (var i = 0, j = this.length; i < j; i++) {
		(type == 'max' || type == 1) ? (array[i] * 1 > result)
				&& (result = array[i] * 1) : (array[i] * 1 < result)
				&& (result = array[i] * 1);
	}
	return result;
};

/**
 * 将两个元素交换
 * 
 * @param {Array}{Object}
 *            array 数组
 * @param {Number}{String}
 *            first 第一个下标
 * @param {Number}{String}
 *            second 第二个下标
 * @return {Object}{Array} 交换后的数组
 */
qinglan.Array.swap = function(array, first, second) {
	var temp = array[first];
	array[first] = array[second];
	array[second] = temp;
	return array;
};
/**
 * 将数组打乱,原理是随机交换两个元素的值,可以设定洗牌次数
 * 
 * 
 * @param {Array}
 *            array 数组
 * @param {number}
 *            times 洗牌次数,如果不存在就按数组长度计算
 */
qinglan.Array.random = function(array, times) {
	var len = array.length, index_1, index_2;
	times = times || len;
	for (var i = 0; i < times; i++) {
		index_1 = Math.floor(Math.random() * len);
		while ((index_2 = Math.floor(Math.random() * len)) == index_1) {
			continue;
		}
		qinglan.Array.swap(array, index_1, index_2);
	}
	return array;
};
/**
 * 从数组里面计算有多少个指定的对象
 * 
 * @param {Array}
 *            array 数组
 * @param {Object}
 *            item 需要计算的对象
 * @return {Number} 计算值
 */
qinglan.Array.count = function(array, item) {
	var count = 0;
	for (var i = 0, len = array.length; i < len; i++) {
		if (array[i] == item) {
			count++;
		}
	};
	return count;
};
/**
 * 得到数组最后一个元素
 * 
 * @param {Array}
 *            array 数组
 * @return {Object} array数组最后一个元素
 */
qinglan.Array.getTheLast = function(array) {
	return array[array.length - 1];
};
// @include "../extend/Debug.js"
/**
 * @fileOverview 事件通知扩展工具
 * 
 * @version qinglan_listener 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 事件通知类，在对象内部把事件抛出
 * 
 * @param {Srting}
 *            name 本事件实例名字(ID)
 * @param {Object}
 *            target 事件触发对象
 */
qinglan.Listener = function(name, target) {
	this.name = name ? name : qinglan.Listener.index++;
	this.target = target;
	this.advicePool = {};
	
	qinglan.Listener._pool[name] = this;
};
/**
 * 监听器索引
 * 
 * @type Number
 */
qinglan.Listener._index = 0; 
/**
 * 所有事件对象缓存索引
 * 
 * @type Object
 */
qinglan.Listener._pool = {};
/**
 * 根据名字得到事件对象实例
 * 
 * @param {String}
 *            name 实例名字
 * @return {qinglan.Listener} 事件对象实例
 */
qinglan.Listener.getListenerByName = function(name) {
	return qinglan.Listener._pool[name];
};
/**
 * 增加监听的函数
 * 
 * @param {String}
 *            type 事件类型
 * @param {String}
 *            name 监听器名字
 * @param {Function}
 *            advice 监听器
 */
qinglan.Listener.prototype.addAdvice = function(type, name, advice) {
	!this.advicePool[type] && (this.advicePool[type] = []);
	var event = function() {
		advice.apply(this.target || window, arguments);
	};
	this.advicePool[type][name] = event;
};
/**
 * 删除监听函数
 * 
 * @param {String}
 *            type 事件类型
 * @param {String}
 *            name 监听器名字
 */
qinglan.Listener.prototype.removeAdvice = function(type, name) {
	try {
		delete this.advicePool[type][name];
	} catch (e) {
		qinglan.Debug.error('Delete Advice : [' + advice + '] from Listener : [' + this + '] error !');
	}
};
/**
 * 通知所有制定类型的监听器
 * 
 * @param {String}
 *            type 事件类型
 * @param {Array}
 *            args 参数数组
 */
qinglan.Listener.prototype.notify = function(type, args) {
	if (this.advicePool[type]) {
		for (var name in this.advicePool[type]) {
			this.advicePool[type][name].apply(this, args);
		}
	}
};
﻿// @include "Browser.js"
// @include "Type.js"
// @include "Argument.js"
/**
 * @fileOverview Function扩展工具
 * 
 * @version qinglan_function 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * Function扩展命名空间
 * 
 * @type Object
 */
qinglan.Function = qinglan.Function || {};
/**
 * 进行方法绑定
 * 
 * @param {Object}
 *            obj 绑定的对象
 * @param {Function}
 *            fun 绑定的方法
 * @return {Object} 可执行对象
 */
qinglan.Function.bind = function(obj, fun) {
	return function() {
		qinglan.Type.isString(fun) && (fun = obj[fun]);
		!qinglan.Type.isFunction(fun) && (fun = qinglan.Function.emptyFun);
		return fun.apply(obj, qinglan.Argument.toArray(arguments, 2));
	};
};
/**
 * 空的方法
 * 
 * @static
 * @type Function
 */
qinglan.Function.emptyFun = function() {
};

/**
 * 方法反射<br/>
 * 根据tag得到方法的相应部分内容
 * <ul>
 * 		<li><b>body</b> : 方法体</li>
 * 		<li><b>param</b> : 方法参数</li>
 * 		<li><b>name</b> : 方法名字 但是对匿名方法无效</li>
 * 		<li><b>scope</b> : 方法调用链</li>
 *		<li><b>anonymous</b> : 匿名方法方法字串</li>
 * </ul>
 * 
 * @param {Function} fun 方法
 * @param {String} tag 获取反射类型
 * @type Function
 * @public
 * @see http://www.cnblogs.com/rubylouvre/archive/2011/05/30/2062953.html author司徒正美
 */
qinglan.Function.reflect=function(fun,tag){
	if(qinglan.Type.isFunction(fun)){
		var _r_function = /^function\b\s*([\$\S]*)\s*\(/;//得到方法名
		var _r_codebody = /[^{]*\{([\d\D]*)\}$/;//得到方法体
		var _r_params = /[^\(]*\(([^\)]*)\)[\d\D]*/;//得到方法参数
		tag = (tag || 'body').toLowerCase();
		with (func.toString()) {
			return (tag == 'body') ? replace(_r_codebody, '$1').replace(/^\s*|\s*$/g, '')
			: (tag == 'param') ? ((tag=replace(_r_params, '$1')) ? tag.split(/[,\s]+/) : [])
			: (tag == 'name') ? match(_r_function)[1]
			: (tag == 'scope') ? '[function (' +arguments.callee(func, 'param')+ ') {\n' +arguments.callee(func, 'body')+ '\n}][0]'
			: (tag == 'anonymous') ? Function.apply(this, arguments.callee(func, 'param').concat(arguments.callee(func, 'body')))
			: 'Block() with bad arguments.';
		};
	}
};
/**
 * 得到非匿名方法的名字
 * 
 * @public
 * @param {Function} fun 方法
 * @return {String} 方法名字
 */
qinglan.Function.getName=function(fun){
	if(qinglan.Type.isFunction(fun)){
		return fun.name || String(f).match(/^function\s*([^)]*)\(/)[1];
	}
};
﻿// @include "Browser.js"
/**
 * @fileOverview 类型判断类<br/> 本类使用
 *               javascript神秘花园提供的Object.prototype.toString.call方法进行强类型检测
 * 
 * @version qinglan_Type 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 类型工具命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Type = qinglan.Type || {};
/**
 * 判断对象是否为此类型<br/> *
 * 
 * @public
 * @static
 * @see 请参考 javascript神秘花园 <br/> 
 * 		<p style="color : #FFAA3E"> http://bonsaiden.github.com/JavaScript-Garden/zh/#types.typeof </p>
 * @param {String}
 *            type
 * @param {Object}
 *            obj
 * @return {Boolean}
 */
qinglan.Type.is = function(type, obj) {
	var klass = Object.prototype.toString.call(obj).slice(8, -1);
	return obj !== undefined && obj !== null && klass === type;
};
/**
 * 判断对象类型是否为数字
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为数字
 */
qinglan.Type.isNumber = function(obj) {
	return qinglan.Type.is('Number', obj);
};

/**
 * 判断对象类型是否为字符串
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为字符串
 */
qinglan.Type.isString = function(obj) {
	return qinglan.Type.is('String', obj);
};

/**
 * 判断对象类型是否为布尔值
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为布尔值
 */
qinglan.Type.isBoolean = function(obj) {
	return qinglan.Type.is('Boolean', obj);
};
/**
 * 判断对象类型是否为Date对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为Date对象
 */
qinglan.Type.isDate = function(obj) {
	return qinglan.Type.is('Date', obj);
};
/**
 * 判断对象类型是否为Array对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为Array对象
 */
qinglan.Type.isArray = function(obj) {
	return qinglan.Type.is('Array', obj);
};
/**
 * 判断对象类型是否为Function对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为Function对象
 */
qinglan.Type.isFunction = function(obj) {
	return qinglan.Type.is('Function', obj);
};

/**
 * 判断对象类型是否为RegExp对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为RegExp对象
 */
qinglan.Type.isRegExp = function(obj) {
	return qinglan.Type.is('RegExp', obj);
};

/**
 * 判断对象类型是否为Object对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为Object对象
 */
qinglan.Type.isObject = function(obj) {
	return qinglan.Type.is('Object', obj);
};

/**
 * 判断对象类型是否为Error对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为Error对象
 */
qinglan.Type.isError = function(obj) {
	return qinglan.Type.is('Error', obj);
};
/**
 * 判断对象是否定义
 * 
 * @deprecated
 * @public
 * @static
 * @param {Object}
 *            varName 需要判断的对象
 * @return {Boolean} 是否定义
 */
qinglan.Type.isDefined = function(varName) {
	// 抛出 ReferenceError 异常
	return typeof varName !== 'undefined';
};

/**
 * 判断对象是否元素节点
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否定义
 */
qinglan.Type.isElement = function(obj) {
	return !!(obj && obj.nodeType == 1);
};
/**
 * 判断对象类型是否为Null对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为Null对象
 */
qinglan.Type.isNull = function(obj) {
	if (qinglan.Browser && qinglan.Browser.isIE) {
		return obj === null;
	}
	return qinglan.Type.is('Null', obj);
};
/**
 * 判断对象类型是否为Undefined对象
 * 
 * @public
 * @static
 * @param {Object}
 *            obj 需要判断的对象
 * @return {Boolean} 是否为Undefined对象
 */
qinglan.Type.isUndefined = function(obj) {
	if (qinglan.Browser && qinglan.Browser.isIE) {
		return obj === undefined;
	}
	return qinglan.Type.is('Undefined', obj);
};
// @include "../code/Browser.js"
// @include "../code/Type.js"
// @include "../code/String.js"
// @include "../code/Array.js"
// @include "../code/Extend.js"
// @include "../extend/Debug.js"
/**
 * @fileOverview 节点css操作工具
 * 
 * @version qinglan_css 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 节点css操作节点命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Css = qinglan.Css || {};
/**
 * 检测元素里面是否有指定的className
 * 
 * @param {Element}
 *            node 节点元素
 * @param {String}
 *            calssName 徐璈检测的className
 * @return {Boolean}
 */
qinglan.Css.hasClass = function(node, calssName) {
	if (qinglan.Type.isElement(node)) {
		return qinglan.Css.inClass(calssName, node.className);
	} else {
		qinglan.Debug.info('The arg node : [' + node+ '] is not a Node');
		return false;
	}
};
/**
 * 检测class是否在指定的class集合中
 * 
 * @param {String}
 *            checkClass 需要检测的cssName
 * @param {String}
 *            totlaClass class集合
 * @return {Boolean} 是否包含在内
 */
qinglan.Css.inClass = function(checkClass, totlaClass) {
	var class_arr = qinglan.String.trim(nodeClass).split(" ");
	for (var i = 0, len = class_arr.length; i < len; i++) {
		if (class_arr[i] == calssName)
			return true;
	}
	return false;
};
/**
 * 把指定的className添加到node.className中
 * 
 * @param {Element}
 *            node 节点元素
 * @param {String}
 *            className 需要添加的className
 */
qinglan.Css.addClass = function(node, className) {
	if (qinglan.Type.isArray(className)) {
		qinglan.Array.each(className, function(value) {
					qinglan.Css.addClass(node, value);
				});
	}
	var nodeClassName = node.className;
	!qinglan.Css.inClass(className, nodeClassName)
			&& (node.className += ' ' + className);
};
/**
 * 把指定的className从node.className中移除
 * 
 * @param {Element}
 *            node 节点元素
 * @param {String}
 *            className 需要添加的className
 */
qinglan.Css.removeClass = function(node, className) {
	if (qinglan.Type.isArray(className)) {
		qinglan.Array.each(className, function(value) {
					qinglan.Css.removeClass(node, value);
				});
	};
	var nodeClassName = node.className;
	qinglan.Css.inClass(className, nodeClassName)
			&& (node.className = qinglan.String.trim(node.className.replace(
					className, '').replace(/\s{2}/g, ' ')));
};
/**
 * 得到节点的所有的class
 * 
 * @param {Element}
 *            node 节点元素
 * @return {Array} className数组
 */
qinglan.Css.getAllClass = function(node) {
	return qinglan.String.trim(node.className).split(/\s{1,}/);
};
/**
 * 设置节点的Style
 * 
 * @param {Element}
 *            node 节点元素
 * @param {Object}
 *            styles cssStyle属性
 */
qinglan.Css.setStyle = function(node, styles) {
	if (qinglan.Type.isArray(node)) {
		qinglan.Css.setStyle(node, style);
	};
	qinglan.Extend.simple(node.style, styles, 1);
};
/**
 * 得到节点的样式
 * 
 * @param {Element}
 *            node 节点元素
 * @param {String}
 *            key cssStyle属性key
 */
qinglan.Css.getStyle = function(node, key) {
	var value = qinglan.Browser.isIE ? node.currentStyle[key] : window
			.getComputedStyle(node, null)[key];
	var num = parseFloat (value);
	return isNaN(num) ? ( value != 'auto' ? value : '' ) : num;
};
/**
 * 设置节点透明度
 * 
 * @param {Element}
 *            node 节点元素
 * @param {Number}
 *            opacity 透明度 [0,1]
 */
qinglan.Css.setOpacity = function(node, opacity) {
	qinglan.Browser.isIE ? qinglan.Css.setStyle(node, {
				'filter' : 'alpha(opacity=' + opacity * 100 + ')'
			}) : qinglan.Css.setStyle(node, {
				'opacity' : opacity
			});
};
/**
 * 得到节点透明度
 * 
 * @param {Element}
 *            node 节点元素
 */
qinglan.Css.getOpacity = function(node) {
	return qinglan.Browser.isIE ? qinglan.Css.getStyle(node, 'filter')
			.match(/opacity=(\d+)/)[1] : qinglan.Css.getStyle(node, 'opacity');
};
/**
 * 设置节点样式接口
 * 
 * @param {Element}
 *            node 节点元素
 * @param {Object}
 *            styles cssStyle属性
 */
qinglan.Css.set = function(node, styles) {
	if (styles['opacity']){
		qinglan.Css.setOpacity(node,styles['opacity']);
		delete styles['opacity'];
	} 
	qinglan.Css.setStyle(node,styles);
};
/**
 * 得到节点样式接口
 * 
 * @param {Element}
 *            node 节点元素
 * @param {String}
 *            key cssStyle属性key
 * @return {String}{Number} cssstyleValue
 */
qinglan.Css.get = function(node, key) {
	if ( key == 'opacity'){
		return qinglan.Css.getOpacity(node);		
	}
	else {
		return qinglan.Css.getStyle(node,key);
	}
};
/**
 * 格式化样式表,过滤掉不能够进行数值变化的style<br/>
 * <b>用于处理动画</b>
 * 
 * @param {Object} style 样式对象
 * @return {Arrya} 样式对象数组
 */
qinglan.Css.formatStyle=function(style) {
	var result = {};
	var count = 0;
	for (var s in style){
		var t = style[s].toString().match(/(\d+)($|([a-z]+))/);
		if (t) {
			result[s] ={};
			result[s].key = s;
			result[s].val = qinglan.Type.isNumber(style[s]) ? style[s] : parseFloat(t[1]);
			result[s].px = t[3] || 0.0;
			count++;
		}
	}
	return {style : result, len : count};
};
// @include "../code/Browser.js"
// @include "../code/Type.js"
// @include "../code/String.js"
// @include "../code/Array.js"
// @include "../code/Extend.js"
// @include "../code/Listener.js"
// @include "Css.js"
// @include "Dom.js"
// @include "Tween.js"
// @include "../extend/Debug.js"
/**
 * @fileOverview dom动画渲染工具
 * 
 * @version qinglan_animate 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * dom动画渲染工具
 * 
 * @type Function
 */
qinglan.Animate = function (id, styleMap, duration,option) {
	
	option = qinglan.Extend.simple({
			delay : 0,
			equal : qinglan.Tween.Quadratic.easeInOut,
			frameRate : 20
		},option,1);
	
	this.id = id ;
	this.ele = $g(id);
	this.duration = duration;
	this.listener = new qinglan.Listener(null,this);
	
	var map =  qinglan.Css.formatStyle(styleMap);
	this.styleMap = map.style;
	this.styleMapLen= map.len;
	
	this.delay =option.delay;
	this.equal = option.equal;
	
	this._data={};
	this._data.nowTime = 0;
	this._data.ispush = false;
	this._data.isPlay = false;
	this.init();

};
/**
 * 动画初始化
 * 
 * @function
 * @public
 */
qinglan.Animate.prototype.init = function() {
	this.duration -= this._data.nowTime; 
	
	var sub = {};
	var begin = {};
	
	for (var s in this.styleMap) { //缓存动画之前所有的差值
		begin[s] = qinglan.Css.get(this.ele, s) || 0;
		sub[s] =  this.styleMap[s].val - begin[s] ;
	}
	this._data.sub = sub;
	this._data.begin = begin;
	
};
/**
 * 动画播放
 * 
 * @function
 * @public
 */
qinglan.Animate.prototype.play = function() {
	var self = this ;
	if(self._data.isPlay){return;}
	if( self.delay ) {
		setTimeout(function(){self.play();}, self.delay);
		self.delay = 0;
	}
	var finishCount = 0;
	var defaultCallBack = function(){
		if(++finishCount == self.styleMapLen){
			self.listener.notify('finish');
		}
	};
	self.interval = qinglan.Animate._change(self,self.styleMap,defaultCallBack);
	self._data.isPlay = true;
	self.listener.notify('play');
};
/**
 * 动画停止
 * 改方法会停止动画的渲染，停止之后不能恢复
 * 
 * @function
 * @public
 */
qinglan.Animate.prototype.stop = function(){
	clearInterval(this.interval);
	this._data.isPlay = false;
	this.listener.notify('stop');
};
/**
 * 动画暂停
 * 调用该方法之后动画会暂停，状态会保存，如果想继续可以使用restart方法
 * @see qinglan.Animate.prototype.restart
 * 
 * @function
 * @public
 */
qinglan.Animate.prototype.pause=function(){
	if(!this._data.isPlay){return false;}
	this._data.ispush = true;
	clearInterval(this.interval);
	this._data.isPlay = false;
	this.listener.notify('pause');
};
/**
 * 动画继续
 * 该方法是使暂停的动画继续渲染
 * 
 * @function
 * @public 
 */
qinglan.Animate.prototype.restart=function(){
	if(this._data.isPlay){return false;}
	this._data.ispush = false;
	this.init();
	this.listener.notify('restart');
	this.play();
};
/**
 * 设置监听对象
 * @param {qinglan.Listener} listener 监听对象
 * 					支持监听类型方法 finish play pause restart
 * 
 * @function
 * @public
 */
qinglan.Animate.prototype.setListener = function (listener){
	this.listener = listener;
};
/**
 * 动画状态改变函数
 * @param {qinglan.Animate} animate 动画实力
 * @param {Object} styleMap 样式列表
 * @param {Function} callback 回调函数
 * 
 * @function
 * @private
 * @return {Interval} 时间戳对象
 */
qinglan.Animate._change=function(animate,styleMap,callback) {
	var st = (new Date()).getTime();
	var ele = animate.ele;
	var d  = animate.duration;
	var c = animate._data.sub;
	var b = animate._data.begin;
	var interval = setInterval(function() {
		var t = animate._data.nowTime = new Date().getTime() - st;
		if (t > d){
			callback();
			clearInterval(interval);
			return true;
		}
		var styleCurrentMap = {};
		for (var s in styleMap) {
			styleCurrentMap [s] = animate.equal(t,b[s],c[s],d) + styleMap[s].px ;
		}
		qinglan.Css.set(ele,styleCurrentMap);
		return false;
	}, 20);
	return interval;
};
// @include "../code/Browser.js"
// @include "../code/Type.js"
// @include "../code/Array.js"
// @include "../extend/Debug.js"
/**
 * @fileOverview 页面URL操作工具
 * 
 * @version qinglan_url 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 页面URL操作节点命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Url = qinglan.Url || {};
/**
 * 根据指定的key获取在URL QueryString上的参数
 * 
 * @param {String}
 *            key 指定的queryString的值
 */
qinglan.Url.getUrlParam = function(key) {
	return location.search.match(new RegExp(key + '=([^&]*)'))[1];
};
/**
 * 得到所有的URLQueryString的参数
 * 
 * @return {Object} queryString 的Json对象
 */
qinglan.Url.getAllUrlParam = function() {
	var param = location.search.slice(1).split('&');
	var result = {};
	qinglan.Array.each(param, function(value) {
				var par = value.split('=');
				result[par[0]] = par[1];
			});
	return result;
};

// @include "../code/Browser.js"
// @include "../code/Type.js"
// @include "../code/Array.js"
// @include "../extend/Debug.js"
/**
 * @fileOverview AJAX异步加载工具
 * 
 * @version qinglan_Ajax 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * AJAX异步加载工具命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Ajax = qinglan.Ajax || {};

qinglan.Ajax.get = function(url, callback) {
	var xhr = new XMLHttpRequest();
	xhr.onreadystatechange = function() {
		if (xhr.readyState === 4) {
			var error;
			if (xhr.status !== 200 && xhr.status !== 0) {
				error = "Invalid XHR status " + xhr.status;
			} else if (xhr.responseText === "") {
				error = "No content";
			}
			callback(xhr.responseText, error);
		}
	};
	xhr.open("GET", url, true);
	if (xhr.overrideMimeType) {
		xhr.overrideMimeType("application/json");
	}
	xhr.setRequestHeader("If-Modified-Since", "Fri, 01 Jan 1960 00:00:00 GMT"); // no
	// cache
	xhr.send(null);
};
/**
 * @fileOverview 补间动画方式工具
 * 
 * @version qinglan_animate 1.0
 * @static
 * @author wxq wxqqh@qq.com
 * 
 * @see http://www.cnblogs.com/cloudgamer/archive/2009/01/06/Tween.html  author cloudgamer
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 补间动画命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Tween = qinglan.Tween || {};
/**
 * 一次线性方程 ( t )
 * 
 * @namespace
 * @type Object
 */
qinglan.Tween.Linear = qinglan.Tween.Linear || {};
/**
 * 一次线性方程正常模式
 * 
 * <pre>
 * 		c * t / d + b
 * </pre>
 * 
 * @param {Number}
 *            t 时间片，当前时间
 * @param {Number}
 *            b 开始值
 * @param {Number}
 *            c 变化值
 * @param {Number}
 *            d 持续时间
 * @return {Number} 当前计算值
 * 
 */
qinglan.Tween.Linear.normal = function(t, b, c, d) {
	return c * t / d + b;
};
/**
 * 二次线性方程 ( t ^ 2 )
 * 
 * @namespace
 * @type Object
 */
qinglan.Tween.Quadratic = qinglan.Tween.Quadratic || {};
/**
 * 二次线性方程  从0开始加速的缓动
 * 
 * <pre>
 * 		c * ( t /= d ) * t + b
 * </pre>
 * 
 * @param {Number}
 *            t 时间片，当前时间
 * @param {Number}
 *            b 开始值
 * @param {Number}
 *            c 变化值
 * @param {Number}
 *            d 持续时间
 * @return {Number} 当前计算值
 * 
 */
qinglan.Tween.Quadratic.easeIn = function(t, b, c, d) {
	return c * ( t /= d ) * t + b;
};
/**
 * 二次线性方程  减速到0的缓动
 * 
 * <pre>
 * 		- c * ( t /= d ) * ( t - 2 ) + b
 * </pre>
 * 
 * @param {Number}
 *            t 时间片，当前时间
 * @param {Number}
 *            b 开始值
 * @param {Number}
 *            c 变化值
 * @param {Number}
 *            d 持续时间
 * @return {Number} 当前计算值
 * 
 */
qinglan.Tween.Quadratic.easeOut = function(t, b, c, d) {
	return - c * ( t /= d ) * ( t - 2 ) + b; 
};
/**
 * 二次线性方程  前半段从0开始加速，后半段减速到0的缓动
 * 
 * <pre>
 * 		( t /= d / 2 < 1 ) ? ( c / 2 * Math.pow( t, 2 ) + b ) : ( - c /2 * ( ( -- t ) * ( t - 2 ) - 1) + b )
 * </pre>
 * 
 * @param {Number}
 *            t 时间片，当前时间
 * @param {Number}
 *            b 开始值
 * @param {Number}
 *            c 变化值
 * @param {Number}
 *            d 持续时间
 * @return {Number} 当前计算值
 * 
 */
qinglan.Tween.Quadratic.easeInOut = function (t, b, c, d) {
	return  ( (t /= d / 2) < 1 ) ? ( c / 2 * Math.pow( t, 2 ) + b ) : ( - c /2 * ( ( -- t ) * ( t - 2 ) - 1) + b );
};
/**
 * 三次线性方程  ( t ^ 3  )
 * 
 * @namespace
 * @type Object
 */
qinglan.Tween.Cubic = qinglan.Tween.Cubic || {}; 
/**
 * 三次线性方程  从0开始加速的缓动
 * 
 * <pre>
 * 		c * ( t /= d ) * Math.pow( t, 2 ) + b
 * </pre>
 * 
 * @param {Number}
 *            t 时间片，当前时间
 * @param {Number}
 *            b 开始值
 * @param {Number}
 *            c 变化值
 * @param {Number}
 *            d 持续时间
 * @return {Number} 当前计算值
 * 
 */
qinglan.Tween.Cubic.easeIn = function (t, b, c, d) {
	return c * ( t /= d ) * Math.pow( t, 2 ) + b;
};
/**
 * 三次线性方程  减速到0的缓动
 * 
 * <pre>
 * 		- c * ( t /= d ) * ( t - 2 ) + b
 * </pre>
 * 
 * @param {Number}
 *            t 时间片，当前时间
 * @param {Number}
 *            b 开始值
 * @param {Number}
 *            c 变化值
 * @param {Number}
 *            d 持续时间
 * @return {Number} 当前计算值
 * 
 */
qinglan.Tween.Cubic.easeOut = function (t, b, c, d) {
	return c * ( ( t = t / d - 1 ) * Math.pow(t, 2) + 1) +b; 
};
/**
 * 三次线性方程  前半段从0开始加速，后半段减速到0的缓动
 * 
 * <pre>
 * 		 (t /= d /2 <1 ) ? ( c / 2 * Math.pow(t, 3) + b ) : ( c / 2 * ( ( t -=2  ) * Math.pow(t, 2) + 2 ) + b )
 * </pre>
 * 
 * @param {Number}
 *            t 时间片，当前时间
 * @param {Number}
 *            b 开始值
 * @param {Number}
 *            c 变化值
 * @param {Number}
 *            d 持续时间
 * @return {Number} 当前计算值
 * 
 */
qinglan.Tween.Cubic.easeInOut = function(t, b, c, d) {
	return ((t /= d / 2) <1 ) ? ( c / 2 * Math.pow(t, 3) + b ) : ( c / 2 * ( ( t -=2  ) * Math.pow(t, 2) + 2 ) + b );
};
// @include "../code/Browser.js"
// @include "../code/Type.js"
// @include "../extend/Debug.js"
// @include "CSS.js"
/**
 * @fileOverview 页面节点操作工具
 * 
 * @version qinglan_dom 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 页面节点操作节点命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Dom = qinglan.Dom || {};
/**
 * document对象的缓存
 * 
 * @type Document
 */
qinglan.Dom.d = document;
/**
 * 通过ID得到元素接点<br/>如果得不到元素则返回Id字串
 * 
 * @public
 * @function
 * @param {String}
 *            id 元素节点ID
 * @return {String}{Element}
 */
qinglan.Dom.get = function(id) {
	return qinglan.Dom.d.getElementById(id) || id;
};
/**
 * 通过className得到元素
 * 
 * @public
 * @function
 * @param {String}
 *            className 节点元素的ClassName
 * @param {String}
 *            tag 节点的TagName
 * @param {Element}
 *            content 所需要搜索的上下文 ,请使用的时候直接指定上下文节点,为了性能问题
 * @return {Array} 搜索到的节点
 */
qinglan.Dom.getByClass = function(className, tag, content) {
	tag = tag || "*";
	content = content || qinglan.Dom.d;
	var eles = root.getElementsByTagName(tag);
	var result = new Array();
	qinglan.Array.each(eles, function(value) {
				if (qinglan.Css.hasClass(className, eles[i].className)) {
					result.push(eles[i]);
				}
			});
	return result;
};
/**
 * 将节点插入到某节点前面或者后面 <br/> mode 为 'after' 插入节点后面
 * 
 * @public
 * @function
 * @param {Element}
 *            ele 需要插入的节点
 * @param {Element}
 *            target 目标节点
 * @param {String}
 *            mode 插入节点方式 'after' 为插入节点后面
 * @param {Boolean}
 *            copy 是否
 * @return {Boolean} 是否插入成功
 */
qinglan.Dom.insert = function(ele, target, mode, copy) {
	if (qinglan.Type.isElement(ele) && qinglan.Type.isElement(target)) {
		copy && (ele = ele.cloneNode(true));
		var parentNode = target.parentNode;
		if (mode == 'after' || mode == '1') {
			if (parentNode.lastChild == target) {
				parentNode.appendChild(ele);
			} else {
				parentNode.insertBefore(ele, target.nextSibling);
			}
		} else {
			parentNode.insertBefore(ele, target);
		}
		return true;
	} else {
		qinglan.Debug.error('The ele :[' + ele + '] or target '+ target + '] is not Element!!');
		return false;
	}
};
/**
 * 将节点替换某节点
 * 
 * @public
 * @function
 * @param {Element}
 *            ele 需要替换的节点
 * @param {Element}
 *            target 目标节点
 * @param {Boolean}
 *            copy 是否
 * @return {Boolean} 是否插入成功
 */
qinglan.Dom.replace = function(ele, target, copy) {
	try {
		copy && (ele = ele.cloneNode(true));
		var p = target.parentNode;
		p.replaceChild(ele, target);
		return true;
	} catch (e) {
		qinglan.Debug.error('The  target ' + target+ '] is not Element!!');
		return false;
	}
};
/**
 * 根据Key得到ele的属性
 * 
 * @public
 * @function
 * @param {Element}
 *            ele 节点元素 默认是document.body
 * @param {String}
 *            key 需要得到的键
 * @return {Object}{String} key所对应的值
 */
qinglan.Dom.getEleValue = function(ele, key) {
	var node = ele || qinglan.Dom.d.body;
	if (qinglan.Type.isArray(key)) {
		var result = {};
		qinglan.Array.each(key, function(value) {
					result[value] = node[value] || '';
				});
		return result;
	} else {
		return node[key] || '';
	}
};
/**
 * 获取属性映射
 * 
 * @private
 * @type Object
 */
qinglan.Dom.getEleValue._map = {
	client : ['clientWidth', 'clientHeight', 'clientLeft', 'clientTop'],
	scroll : ['scrollWidth', 'scrollHeight', 'scrollLeft', 'scrollTop'],
	offset : ['offsetWidth', 'offsetHeight', 'offsetLeft', 'offsetTop',
			'offsetParent']
};
/**
 * 初始化函数<br/>在文件加载的时候自动执行一次
 * 
 * @field
 * @private
 * @type Boolean
 */
qinglan.Dom._init = (function() {
	// 添加方法
	qinglan.Array.each(['getClient', 'getScroll', 'getOffset'],
			function(value) {
				this[value] = function(ele) {
					return qinglan.Dom.getEleValue(ele,
							qinglan.Dom.getEleValue._map[value.toLowerCase()
									.slice(3)]);
				};
			}, qinglan.Dom);
	return true;
})();
/**
 * getEle函数的引用
 * 
 * @type Function
 */
window.$g = qinglan.Dom.get;
﻿// @include "../code/Extend.js"
// @include "../code/Array.js"
// @include "../code/Type.js"
// @include "../extend/Debug.js"
/**
 * @fileOverview 事件绑定工具
 * 
 * @version qinglan_Browser 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 事件绑定命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Event = qinglan.Event || {};
/**
 * 事件绑定列表
 * 
 * @private
 * @field
 * @type Object
 */
qinglan.Event._listenQueue = {};
/**
 * 事件对象索引id
 * 
 * @type Number
 */
qinglan.Event._eleId = 1;
/**
 * 事件方法索引id
 * 
 * @type Number
 */
qinglan.Event._funId = 1;
/**
 * 键位映射
 * 
 * @public
 * @type Object
 */
qinglan.Event.Keys = {
	BACKSPACE : 8,
	TAB : 9,
	RETURN : 13,
	ESC : 27,
	SPACE : 32,
	LEFT : 37,
	UP : 38,
	RIGHT : 39,
	DOWN : 40,
	DELETE : 46
};
/**
 * 进行事件绑定<br/>
 * 对绑定事件的元素节点增加eventId属性作为事件缓存索引,事件都会缓存在qinglan.Event._listenQueue对象中
 * 
 * @param {Element}
 *            ele 节点元素
 * @param {String}
 *            type 事件类型
 * @param {Function}
 *            fun 事件触发函数
 * @param {Array}
 *            argArray 事件触发函数所需要的参数
 */
qinglan.Event.on = function(ele, type, fun, argArray) {
	if (qinglan.Type.isArray(ele)) {// 进行数组处理
		qinglan.Array.each(ele, function(value) {
					qinglan.Event.on(ele, type, fun);
				});
	}
	try {
		// 这里进行一系列的初始化操作,只会进行一次
		!ele.__eventEleId && (ele.__eventEleId = qinglan.Event._eleId++);// 添加事件对象索引ID
		!fun.__eventFunId && (fun.__eventFunId = qinglan.Event._funId++);// 添加方法索引ID
		var eventQueue = qinglan.Event._listenQueue;
		!eventQueue[ele.__eventEleId] && (eventQueue[ele.__eventEleId] = {}); // 初始化监听队列

		var eventFun = eventQueue[ele.__eventEleId][fun.__eventFunId] = function(
				e) {
			fun.apply(ele, !argArray
							? [qinglan.Event.getEvent(e)]
							: [qinglan.Event.getEvent(e)].concat(argArray));
		};

		if (ele.addEventListener) {
			ele.addEventListener(type, eventFun, false);
		} else if (ele.attachEvent) {
			// 适用用IE浏览器
			ele.attachEvent('on' + type, eventFun);
		}
		return true;
	} catch (e) {
		qinglan.Debug.error('Add the fun : [' + fun + '] into listenQueue failed!!');
	}
};
/**
 * 移除事件绑定
 * 
 * @param {Element}
 *            ele 节点元素
 * @param {String}
 *            type 事件类型
 * @param {Function}
 *            fun 事件触发函数
 */
qinglan.Event.remove = function(ele, type, fun) {
	if (qinglan.Type.isArray(ele)) {// 进行数组处理
		qinglan.Array.each(ele, function(value) {
					qinglan.Event.remove(ele, type, fun);
				});
	}
	var eventQueue = qinglan.Event._listenQueue;
	try {
		var eventFun = eventQueue[ele.__eventEleId][fun.__eventFunId];
		if (ele.removeEventListener) {
			ele.removeEventListener(type, eventFun);
		} else {
			ele.detachEvent('on' + type, eventFun);
		}
		return delete eventQueue[ele.__eventEleId][fun.__eventFunId];
	} catch (e) {
		qinglan.Debug.error('The fun : [' + fun + '] is not in the listenQueue !!');
	}
};
/**
 * 获取事件对象
 * 
 * @param {Event}
 *            event 事件源
 * @return {Event}
 */
qinglan.Event.getEvent = function(event) {
	return window.event || event;
};
/**
 * 得到触发事件元素
 * 
 * @param {Event}
 *            event 事件源
 * @return {Element}
 */
qinglan.Event.getTarget = function(event) {
	event = qinglan.Event.getEvent(event);
	return event.srcElement || e.target;
};
/**
 * 禁止默认行为
 * 
 * @param {Event}
 *            event 事件源
 */
qinglan.Event.preventDefault = function(event) {
	event = qinglan.Event.getEvent(event);
	if (event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
};
/**
 * 得到鼠标坐标
 * 
 * @param {Event}
 *            event 事件源 p
 * @return {Object} 鼠标坐标x,y
 */
qinglan.Event.getMousePosition = function(event) {
	event = qinglan.Event.getEvent(event);
	var de = document.documentElement;
	var db = document.body;
	return {
		x : event.pageX || (event.clientX + (de.scrollLeft || db.scrollLeft)),
		y : event.pageY || (event.clientY + (de.scrollLeft || db.scrollLeft))
	};
};
/**
 * 禁止冒泡
 * 
 * @param {Event}
 *            event 事件源
 */
qinglan.Event.cancelBubble = function(event) {
	event = qinglan.Event.getEvent(event);
	if (event.stopPropagation) {
		event.stopPropagation();
	} else {
		if (!event.cancelBubble) {
			event.cancelBubble = true;
		}
	}
};

/**
 * 鼠标悬停函数兼容
 * 
 * @param {Element}
 *            ele 节点元素
 * @param {Function}
 *            fnOver 鼠标进入事件触发函数
 * @param {Function}
 *            fnOut 鼠标离开事件触发函数
 * @param {Array}
 *            argArray 事件触发函数所需要的参数
 */
qinglan.Event.hover = function(ele, fnOver, fnOut, argArray) {
	qinglan.Event.mouseOver(ele, fnOver, argArray);
	qinglan.Event.mouseOut(ele, fnOut, argArray);
};
/**
 * 鼠标进入函数兼容
 * 
 * @param {Element}
 *            ele 节点元素
 * @param {Function}
 *            fun 事件触发函数
 * @param {Array}
 *            argArray 事件触发函数所需要的参数
 */
qinglan.Event.mouseEnter = function(ele, fun, argArray) {
	qinglan.Event.mouseOver(ele, fun, argArray);
};
/**
 * 鼠标离开函数兼容
 * 
 * @param {Element}
 *            ele 节点元素
 * @param {Function}
 *            fun 事件触发函数
 * @param {Array}
 *            argArray 事件触发函数所需要的参数
 */
qinglan.Event.mouseLeave = function(ele, fun, argArray) {
	qinglan.Event.mouseOut(ele, fun, argArray);
};

/**
 * 初始化事件绑定 <br/>只会调用一次
 * 
 * @field
 * @private
 * @type Boolean
 */
qinglan.Event._init = (function() {
	// 添加事件
	qinglan.Array.each(['click', 'mouseDown', 'mouseUp', 'mouseOver',
					'mouseMove', 'mouseOut', 'focus', 'blur', 'keyDown',
					'keyPress', 'keyUp'], function(value) {
				this[value] = function(ele, fun, argArray) {
					return qinglan.Event.on(ele, value.toLocaleLowerCase(),
							fun, argArray);
				};
			}, qinglan.Event);
	// 删除事件
	qinglan.Array.each(['reClick', 'reMouseDown', 'reMouseUp', 'reMouseOver',
					'reMouseMove', 'reMouseOut', 'reFocus', 'reBlur',
					'reKeyDown', 'reKeyPress', 'reKeyUp'], function(value) {
				this[value] = function(ele, fun) {
					return qinglan.Event.remove(ele, value.toLowerCase()
									.slice(2), fun);
				};
			}, qinglan.Event);
	return true;
})();
/**
 * @fileOverview 补间动画方式扩展工具
 * 
 * @version qinglan_animate 1.0
 * @static
 * @author wxq wxqqh@qq.com
 * 
 * @see http://www.cnblogs.com/cloudgamer/archive/2009/01/06/Tween.html author
 *      cloudgamer
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 补间动画命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Tween = qinglan.Tween || {};
/**
 * 四次线性方程（t^4）
 * 
 * @type Object
 */
qinglan.Tween.Quartic = {
	easeIn : function(t, b, c, d) {
		return c * (t /= d) * t * t * t + b;
	},
	easeOut : function(t, b, c, d) {
		return -c * ((t = t / d - 1) * t * t * t - 1) + b;
	},
	easeInOut : function(t, b, c, d) {
		if ((t /= d / 2) < 1)
			return c / 2 * t * t * t * t + b;
		return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
	}
};
/**
 * 五次线性方程（t^4）
 * 
 * @type Object
 */
qinglan.Tween.Quintic = {
	easeIn : function(t, b, c, d) {
		return c * (t /= d) * t * t * t * t + b;
	},
	easeOut : function(t, b, c, d) {
		return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
	},
	easeInOut : function(t, b, c, d) {
		if ((t /= d / 2) < 1)
			return c / 2 * t * t * t * t * t + b;
		return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
	}
};
/**
 * 一次正弦方程（ sin(t) ）
 * 
 * @type Object
 */
qinglan.Tween.Sinusoidal = {
	easeIn : function(t, b, c, d) {
		return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
	},
	easeOut : function(t, b, c, d) {
		return c * Math.sin(t / d * (Math.PI / 2)) + b;
	},
	easeInOut : function(t, b, c, d) {
		return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
	}
};
/**
 * 指数曲线方程（ 2 ^ t ）
 * 
 * @type Object
 */
qinglan.Tween.Exponential = {
	easeIn : function(t, b, c, d) {
		return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
	},
	easeOut : function(t, b, c, d) {
		return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
	},
	easeInOut : function(t, b, c, d) {
		if (t == 0)
			return b;
		if (t == d)
			return b + c;
		if ((t /= d / 2) < 1)
			return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
		return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
	}
};
/**
 * 园方程（ sqrt(1-t^2) ）
 * 
 * @type Object
 */
qinglan.Tween.Circular = {
	easeIn : function(t, b, c, d) {
		return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
	},
	easeOut : function(t, b, c, d) {
		return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
	},
	easeInOut : function(t, b, c, d) {
		if ((t /= d / 2) < 1)
			return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
		return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
	}
};
/**
 * 指数衰减的正弦曲线
 * 
 * @type Object
 */
qinglan.Tween.Elastic = {
	easeIn : function(t, b, c, d, a, p) {
		if (t == 0)
			return b;
		if ((t /= d) == 1)
			return b + c;
		if (!p)
			p = d * .3;
		if (!a || a < Math.abs(c)) {
			a = c;
			var s = p / 4;
		} else
			var s = p / (2 * Math.PI) * Math.asin(c / a);
		return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s)
				* (2 * Math.PI) / p))
				+ b;
	},
	easeOut : function(t, b, c, d, a, p) {
		if (t == 0)
			return b;
		if ((t /= d) == 1)
			return b + c;
		if (!p)
			p = d * .3;
		if (!a || a < Math.abs(c)) {
			a = c;
			var s = p / 4;
		} else
			var s = p / (2 * Math.PI) * Math.asin(c / a);
		return (a * Math.pow(2, -10 * t)
				* Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b);
	},
	easeInOut : function(t, b, c, d, a, p) {
		if (t == 0)
			return b;
		if ((t /= d / 2) == 2)
			return b + c;
		if (!p)
			p = d * (.3 * 1.5);
		if (!a || a < Math.abs(c)) {
			a = c;
			var s = p / 4;
		} else
			var s = p / (2 * Math.PI) * Math.asin(c / a);
		if (t < 1)
			return -.5
					* (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s)
							* (2 * Math.PI) / p)) + b;
		return a * Math.pow(2, -10 * (t -= 1))
				* Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
	}
};
/**
 * 超过范围的三次方方程
 * 
 * @type Object
 */
qinglan.Tween.Back = {
	easeIn : function(t, b, c, d, s) {
		if (s == undefined)
			s = 1.70158;
		return c * (t /= d) * t * ((s + 1) * t - s) + b;
	},
	easeOut : function(t, b, c, d, s) {
		if (s == undefined)
			s = 1.70158;
		return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
	},
	easeInOut : function(t, b, c, d, s) {
		if (s == undefined)
			s = 1.70158;
		if ((t /= d / 2) < 1)
			return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
		return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
	}
};
/**
 * 指数衰减的反弹方程
 * 
 * @type Object
 */
qinglan.Tween.Bounce = {
	easeIn : function(t, b, c, d) {
		return c - Tween.Bounce.easeOut(d - t, 0, c, d) + b;
	},
	easeOut : function(t, b, c, d) {
		if ((t /= d) < (1 / 2.75)) {
			return c * (7.5625 * t * t) + b;
		} else if (t < (2 / 2.75)) {
			return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
		} else if (t < (2.5 / 2.75)) {
			return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
		} else {
			return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
		}
	},
	easeInOut : function(t, b, c, d) {
		if (t < d / 2)
			return Tween.Bounce.easeIn(t * 2, 0, c, d) * .5 + b;
		else
			return Tween.Bounce.easeOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
	}
};
﻿// @include "../code/Function.js"
/**
 * @fileOverview 终端记录类<br/> 本类使用console完成记录工作
 * 
 * @version qinglan_Debug 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 类型工具命名空间
 * 
 * @namespace
 * @type Object
 */
qinglan.Debug = qinglan.Debug || {};
/**
 * debug初始化函数<br/> 为了在debug模式下ie不报错，重新覆盖window.console对象<br/>
 * 本函数会在加载本文件的时候自动运行
 * 
 * @static
 * @private
 * @type Function
 */
qinglan.Debug.init = (function() {
	if (!window.console) {
		window.console = {};
		var methods = ["log", "debug", "info", "warn", "error", "assert",
				"dir", "dirxml", "group", "groupEnd", "time", "timeEnd",
				"count", "trace", "profile", "profileEnd"];
		for (var i = 0, method; method = methods[i++];)
			window.console[method] = qinglan.Function.emptyFun();
	}
	return true;
})();
/**
 * 是否处于debug调试模式<br/> 在调试模式下会输出调试提示信息
 * 
 * @type Boolean
 */
qinglan.Debug.debugMode = true;
/**
 * 进行log输出
 * 
 * @private
 * @function
 * @param {String}
 *            logger console中的logger类型
 * @param {Object}
 *            args 需要进行log的参数
 */
qinglan.Debug._logger = function(logger, args) {
	if(!qinglan.Debug.debugMode){return ;}
	try {
		console[logger].apply(console, args);
	} catch (e) {
		// workaround for IE9
		try {
			for (var i = 0, arr = []; i < args.length; i++) {
				arr.push(args[i]);
			}
			console[logger](arr.join(' '));
		} catch (e) {
			// opera in old version 
			if (window.opera && opera.postError) {
				opera.postError.call(null,args);
			}
		}
	}
};
/**
 * 进行info类型的log
 * 
 * @public
 * @function
 */
qinglan.Debug.info = function() {
	qinglan.Debug._logger('info', arguments);
};
/**
 * 进行error类型的log
 * 
 * @public
 * @function
 */
qinglan.Debug.error = function() {
	qinglan.Debug._logger('error', arguments);
};
/**
 * 记录断言错误
 * 
 * @public
 * @function
 */
qinglan.Debug.assert = function(expr, text) {
	if (!expr) {
		qinglan.Debug._logger('error', 'assertion failed!', text);
		throw new Error('assertion failed! ' + text);
	}
};
// @include "../code/Namespace.js"
// @include "../code/Function.js"
// @include "../code/Tmpl.js"
/**
 * @fileOverview aop实现工具类
 * 
 * @version qinglan_element 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * aop命名空间<br/>
 * 
 * @namespace
 * @type Object
 */
qinglan.Aop = qinglan.Aop || {};
/**
 * 添加aop支持的方法的索引
 * 
 * @private
 * @static
 * @type Number
 */
qinglan.Aop.__methodId = 1;
/**
 * 添加aop支持的通知的索引
 * 
 * @private
 * @static
 * @type Number
 */
qinglan.Aop.__adviceId = 1;
/**
 * aop支持缓存
 * 
 * @private
 * @static
 * @type Object
 */
qinglan.Aop.__AdvicePool = {};
/**
 * AOP 模式,设定为需要判断输入状态机(前一状态机)的状态
 * 
 * @public
 * @static
 * @type String
 */
qinglan.Aop.ALLOW_MODE_IN = 'in';
/**
 * AOP 模式,设定为需要判断输出状态机(当前状态机)的状态
 * 
 * @public
 * @static
 * @type String
 */
qinglan.Aop.ALLOW_MODE_OUT = 'out';
/**
 * aop方向，设定为方法执行之前
 * 
 * @type String
 */
qinglan.Aop.ALLOW_DIRECTION_BEFORE = 'before';
/**
 * aop方向，设定为方法执行之后
 * 
 * @type String
 */
qinglan.Aop.ALLOW_DIRECTION_AFTER = 'after';
/**
 * 进行状态机验证的断言
 * 
 * @public
 * @static
 * @type Object
 */
qinglan.Aop.ALLOW_ASSERT_EQUATION = {
	/**
	 * 默认的验证函数
	 * 
	 * @public
	 * @static
	 * @type Function
	 */
	NORMAL : qinglan.Function.emptyFun,
	/**
	 * 默认的验证结果,为真
	 * 
	 * @public
	 * @static
	 * @type Boolean
	 */
	TRUE : true,
	/**
	 * 默认的验证结果,为假
	 * 
	 * @public
	 * @static
	 * @type Boolean
	 */
	FALSE : false
};

/**
 * 添加aop支持
 * 
 * @param {String}
 *            methodNamespace 需要添加aop支持的方法的命名空间
 * @param {Function}
 *            Advice 需要添加的通知的方法
 * @param {String}
 *            direction aop验证方向 <br/>
 *            <b>qinglan.Aop.ALLOW_DIRECTION_BEFORE(目标函数执行前)</b> 或者
 *            <b>qinglan.Aop.ALLOW_DIRECTION_AFTER(目标函数执行后)</b>
 * @param {String}
 *            mode aop验证模式 <br/><b>qinglan.Aop.ALLOW_MODE_IN(判断advice前一状态)</b>
 *            或者 <b>qinglan.Aop.ALLOW_MODE_OUT(判断当前advice输出状态)</b>
 * @param {Object}{Function}
 *            assert aop验证断言
 * @public
 * @function
 */
qinglan.Aop.addAdvice = function(methodNamespace, advice, direction, mode,
		assert) {
	var aop_init = qinglan.Aop._initAdviceSupport(methodNamespace, advice);
	var nsAdvice = qinglan.Namespace.generate(aop_init.method.__aop_support_id,
			direction);
	var ns = qinglan.Namespace.get(nsAdvice, qinglan.Aop.__AdvicePool);
	if (!!ns) {
		ns[advice.__aop_advice_id] = {
			'advice' : aop_init.advice,
			'mode' : mode,
			'assert' : assert
		};
		qinglan.Aop._bindAop(methodNamespace, aop_init.method);
	} else {
		qinglan.Debug.error('The function :[' + methodNamespace
						+ '] init aop support Error!!');
		return false;
	}
};
/**
 * 初始化aop支持
 * 
 * @param {String}
 *            methodNamespace 需要添加aop支持的方法的命名空间
 * @param {Function}
 *            Advice 需要添加的通知的方法
 * @private
 * @function
 */
qinglan.Aop._initAdviceSupport = function(methodNamespace, advice) {
	var method = qinglan.Namespace.get(methodNamespace);// 得到命名空间所指向的实体
	// 对实体添加aop支持id,只执行一次
	!method.__aop_support_id
			&& (method.__aop_support_id = qinglan.Aop.__methodId++);
	// 对实体添加aop初始化标志,只执行一次
	!method.__aop_support_init && (method.__aop_support_init = false);
	// 对实体添加aop绑定标志,只执行一次
	!method.__aop_support_bind && (method.__aop_support_bind = false);
	// 对通知添加aop通知id,只执行一次
	!advice.__aop_advice_id
			&& (advice.__aop_advice_id = qinglan.Aop.__adviceId++);
	// 进行命名空间初始化
	if (!method.__aop_support_init) {
		qinglan.Aop.__AdvicePool[method.__aop_support_id] = {
			before : {},
			after : {},
			origin : method
		};
		method.__aop_support_init = true;
	};
	return {
		'method' : method,
		'advice' : advice
	};
};

qinglan.Aop._bindAop = function(methodNamespace, method) {
	var flag = true;
	/**
	 * 进行aop调用
	 */
	var _doAop = function() {
		/**
		 * 记录当前返回值
		 */
		var currentReturn = true;
		/**
		 * 进行断言判断
		 * 
		 * @param {Object}
		 *            assert 断言
		 * @param {Object}
		 *            returnValue 需要断言对象，为函数返回值
		 */
		var doAssert = function(assert, returnValue) {
			if (qinglan.Type.isFunction(assert)) {
				return assert.call(null, returnValue);
			} else {
				return assert === returnValue;
			}
		};
		/**
		 * 记录断言失败结果
		 * 
		 * @param {Object}
		 *            assert 断言
		 * @param {Object}
		 *            returnValue 需要断言对象，为函数返回值
		 * @param {String}
		 *            direction aop验证方向
		 * @param {String}
		 *            mode aop验证模式
		 */
		var logAssert = function(assert, returnValue, direction, mode) {
			qinglan.Debug.info(qinglan.Tmpl.smTmpl('Do {direction} {mode} Assert to assert :[{assert}] & currentReturn :[{returnValue}] ',{
												'direction' : direction,
												'mode' : mode,
												'assert' : assert,
												'returnValue' : returnValue
											}));
		};
		/**
		 * 进行aop执行通知
		 * 
		 * @param {String}
		 *            direction aop验证方向
		 */
		var doAdvice = function(direction, args) {
			var adviceChain = qinglan.Aop.__AdvicePool[method.__aop_support_id][direction];
			for (var id in adviceChain) {
				var advice = adviceChain[id];
				if (advice.mode == 'in') {// in 模式，先对输入前状态进行判断,再执行函数
					if (doAssert(advice.assert, currentReturn)) {
						currentReturn = advice.advice.apply(this, args);
					} else {
						logAssert(advice.assert, currentReturn, direction,
								advice.mode);
						flag = false;
						break;

					}
				} else {// out模式，执行函数，对当前函数输出状态进行判断
					currentReturn = advice.advice.apply(this, args);
					if (!doAssert(advice.assert, currentReturn)) {
						logAssert(advice.assert, currentReturn, direction,
								advice.mode);
						flag = false;
						break;
					}
				}
			}
		};
		var origin = qinglan.Aop.__AdvicePool[method.__aop_support_id].origin;
		// 开始执行AOP
		doAdvice.call(origin, 'before', arguments);// Before
		if (flag && currentReturn) {
			originReturn = origin.apply(this, arguments);
			currentReturn = originReturn;
			doAdvice.call(origin, 'after', arguments);// After
			if (!flag) {
				 qinglan.Debug.info('AOP Do After Advice Failed !!');
				return false;
			}
			return originReturn;
		} else {
			qinglan.Debug.info('AOP Do Before Advice Failed !!');
			return false;
		}
	};
	var ns = qinglan.Namespace.create(methodNamespace, window, true);
	if (!ns.instance[ns.key].__aop_support_bind) {// 就行AOP绑定
		var aop_support_id = ns.instance[ns.key].__aop_support_id;
		var aop_support_init = ns.instance[ns.key].__aop_support_init;
		var aop_support_bind = ns.instance[ns.key].__aop_support_bind;
		ns.instance[ns.key] = function() {
			_doAop.apply(this, arguments);
		};
		ns.instance[ns.key].__aop_support_id = aop_support_id;
		ns.instance[ns.key].__aop_support_init = aop_support_init;
		ns.instance[ns.key].__aop_support_bind = true;
	}
};
/**
 * 刪除aop通知
 * 
 * @param {String}
 *            methodNamespace 需要添加aop支持的方法的命名空间
 * @param {Function}
 *            Advice 需要添加的通知的方法
 * @param {String}
 *            direction aop验证方向
 * @param {String}
 *            mode aop验证模式
 * @public
 * @function
 */
qinglan.Aop.removeAdvice = function(methodNamespace, advice, direction) {
	var method = qinglan.Namespace.get(methodNamespace);// 得到命名空间所指向的实体
	try {
		delete qinglan.Aop.__AdvicePool[method.__aop_support_id][direction][advice.__aop_advice_id];
	} catch (e) {
		qinglan.Aop.__AdvicePool[aop_support_id][direction][advice.__aop_advice_id] = function() {
			return true;
		};
		qinglan.Debug.info('The action of "removeAdvice" the method:['+ methodNamespace + '] & advice :[' + advice+ '] & direction :[' + direction + ']failed!!');
	}

};
/**
 * 删除命名空间的所有添加的通知
 * 
 * @param {String}
 *            methodNamespace 需要添加aop支持的方法的命名空间
 * @public
 * @function
 */
qinglan.Aop.clearAllAdvice = function(methodNamespace) {
	var method = qinglan.Namespace.get(methodNamespace);// 得到命名空间所指向的实体
	var aop_support_id = method.__aop_support_id;
	try {
		delete qinglan.Aop.__AdvicePool[aop_support_id];
	} catch (e) {
		qinglan.Aop.__AdvicePool[aop_support_id] = {};
		qinglan.Debug.info('The action of "clearAllAdvice" the method:['+ methodNamespace + '] failed!!');
	}

};

/**
 * 
 * @param {String}
 *            methodNamespace 需要添加aop支持的方法的命名空间
 * @param {Function}
 *            advice 需要添加的通知的方法
 * @param {String}
 *            mode aop验证模式 <br/><b>qinglan.Aop.ALLOW_MODE_IN(判断advice前一状态)</b>
 *            或者 <b>qinglan.Aop.ALLOW_MODE_OUT(判断当前advice输出状态)</b><br/>默认是OUT
 * @param {Object}
 *            assert 断言,默认是true
 * @public
 * @function
 */
qinglan.Aop.before = function(methodNamespace, advice, mode, assert) {
	qinglan.Aop.addAdvice(methodNamespace, advice,
			qinglan.Aop.ALLOW_DIRECTION_BEFORE, mode
					|| qinglan.Aop.ALLOW_MODE_OUT, assert || true);

};
/**
 * @param {String}
 *            methodNamespace 需要添加aop支持的方法的命名空间
 * @param {Function}
 *            advice 需要添加的通知的方法
 * @param {String}
 *            mode aop验证模式 <br/><b>qinglan.Aop.ALLOW_MODE_IN(判断advice前一状态)</b>
 *            或者 <b>qinglan.Aop.ALLOW_MODE_OUT(判断当前advice输出状态)</b><br/>默认是OUT
 * @param {Object}
 *            assert 断言,默认是true
 * @public
 * @function
 */
qinglan.Aop.after = function(methodNamespace, advice, mode, assert) {
	qinglan.Aop.addAdvice(methodNamespace, advice,
			qinglan.Aop.ALLOW_DIRECTION_AFTER, mode
					|| qinglan.Aop.ALLOW_MODE_OUT, assert || true);
};
// @include "../code/Namespace.js"
// @include "../code/Function.js"
// @include "../code/Tmpl.js"
/**
 * @fileOverview Object.watch 兼容实现工具
 * 
 * @version watch 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};

/**
 * Watch 属性监听命名空间<br/>
 * 
 * @namespace
 * @type Object
 */
qinglan.Watch={};
/**
 * 是否已经属性绑定，此属性方法会直接扩展Object原型
 * @private
 * @static
 * @type Boolean
 */
qinglan.Watch.__isBindWatch = false;
/**
 * 进行watch绑定
 * 
 * @public
 * @static
 * @type Function
 */
qinglan.Watch.bindWatch=function(){
	if ( !qinglan.Watch.__isBindWatch && !Object.prototype.watch) {//firefox 原生就支持这个方法
		Object.prototype.watch=function(prop,handler){
			var oldValue = this[prop];
			var newValue = oldValue;
			
			var __getter__ = function(){
				return newValue;
			};
			
			var __setter__ = function(val){
				oldValue = newValue;
				return newValue = handler.call(this,prop,oldValue,newValue);
			};
			
			if (delete this[prop]){
				if(Object.defineProperty){// ECMAScript5
					Object.defineProperty(this,prop,{get : __getter__ , set : __setter__ });
				}else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__){//Fix
					Object.prototype.__defineGetter__.call(this,prop,__getter__);
					Object.prototype.__defineSetter__.call(this,prop,__setter__);
				}
	 		}
		};
	}
	
	if ( !__isBindWatch && !Object.prototype.unwatch){
		Object.prototype.unwatch = function(prop){
			var value = this[prop];
			delete this[prop];
			this[prop] = value;
		};
	}
	qinglan.Watch.__isBindWatch=true;
	return true;
};
﻿// @include "code/Browser.js"
// @include "code/Type.js"
// @include "extend/Debug.js"
/**
 * @fileOverview 异步加载工具
 * 
 * @version qinglan_Import 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};
/**
 * 异步加载js组件
 * 
 * @type Object
 */
qinglan.Import = qinglan.Import || {};
/**
 * 加载js文件
 * 
 * @param {String}
 *            src js文件请求地址
 * @param {Function}
 *            callback 回调函数
 * @param {Object}
 *            param 回调函数参数
 * 
 */
qinglan.Import.js = function(src, callback, param) {
	var d = document;
	var scriptTag = document.createElement("script");
	scriptTag.src = src;
	d.body.appendChild(scriptTag);
	if (qinglan.Type.isUndefined(callback)) {
		scriptTag.onload = function() {
			try {
				callback.call(window, param);
			} catch (e) {
				qinglan.Debug.error('Load js file : [ ' + src + ' ]faild ');
			}
		};
		scriptTag.onreadystatechange = function() {
			if (this.readyState == "complete" || this.readyState == "loaded") {
				try {
					callback.call(window, param);
				} catch (e) {
					qinglan.Debug.error('Load js file : [ ' + src + ' ]faild ');
				}
			}
		};
	}
};
/**
 * 引入css文件
 * 
 * @param {String}
 *            src css文件请求地址
 */
qinglan.Import.css = function(src) {
	var node = document.createElement("link");
	node.rel = "stylesheet";
	node.type = "text/css";
	node.href = src;
	document.getElementsByTagName("head")[0].appendChild(node);
};
/**
 * 引入图片文件
 * 
 * @param {String}
 *            src 图片地址
 * @param {Function}
 *            callback
 * @return {Image} 图片对象
 */
qinglan.Import.img = function(src, callback) {
	var img = new Image();
	img.onload = function() {
		callback.call(img);
		this.onload = null;
	};
	img.src = src;
	return img;
};
﻿// @include "code/Browser.js"
// @include "code/Type.js"
// @include "extend/Debug.js"
// @include "code/Array.js"
/**
 * @fileOverview dom文档onready函数工具
 * 
 * @version qinglan_onready 1.0
 * @static
 * @author wxq wxqqh@qq.com
 */
/**
 * 命名空间
 * 
 * @namespace
 * @type Object
 */
window.qinglan = window.qinglan || {};

/**
 * dom加载完后即执行fun
 * 
 * @param {Function}
 *            fun 需要在domOnready时候执行的方法
 * @type function
 */
qinglan.onReady = function(fun) {
	if (qinglan.Type.isFunction(fun)) {
		qinglan.onReady._loadingFun.push(fun);
	} else {
		qinglan.Debug.error('The Object :[' + fun + '] is not a Function!!');
		return false;
	}
	if (qinglan.onReady._firstTime) {
		qinglan.onReady._firstTime = false;
		if (!qinglan.Browser.isIE) {
			document.addEventListener('DOMContentLoaded', function() {
						qinglan.onReady._fireFun();
					}, false);
			return false;
		}
		// 尝试检测document.doScroll是否可以用
		(function() {
			try {
				document.documentElement.doScroll('left');
			} catch (e) {
				qinglan.onReady._timeout = setTimeout(arguments.callee, 0);
				return false;
			}
			qinglan.onReady._fireFun();
			clearTimeout(qinglan.onReady._timeout);
		})();
		//
		document.onreadystatechange = function() {
			if (document.readyState == 'complete') {
				document.onreadystatechange = null;
				qinglan.onReady._fireFun();
			}
		};
		return false;
	}

};
/**
 * 是否dom加载完成
 * 
 * @private
 * @field
 * @type Boolean
 */
qinglan.onReady.isReady = false;
/**
 * 需要dom加载完成时候调用的函数
 * 
 * @private
 * @field
 * @type Array
 */
qinglan.onReady._loadingFun = new Array();
/**
 * timeout缓存对象
 * 
 * @private
 * @field
 * @type Object
 */
qinglan.onReady._timeout = null;
/**
 * 是否第一次进入onready绑定时间
 * 
 * @private
 * @field
 * @type Object
 */
qinglan.onReady._firstTime = true;
/**
 * 进行事件调用
 */
qinglan.onReady._fireFun = function() {
	qinglan.onReady.isReady = true;
	qinglan.Array.each(qinglan.onReady._loadingFun, function(fun) {
				fun.call(window);
			}, window);
	qinglan.onReady._loadingFun = new Array();
};
